<?php


namespace models\Business;


use Common\AccessToken4Api;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ServerException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Hashids\Hashids;
use models\Business\Tbk\TbkProduct;
use models\DAO\AlibabafavourModel;
use models\DAO\MemberModel;
use models\DAO\TbkfavourModel;
use models\Exception\Business\AlibabacategoryException;
use models\Exception\Business\AlibabaproductException;
use models\Exception\Business\MemberException;
use models\Exception\Business\OrderException;
use models\Exception\Business\TbkproductException;
use models\Exception\DAO\ModelDriverException;
use models\Exception\DAO\ModelException;
use models\Exception\DAO\ModelReflectionException;
use models\Exception\DAO\ModelSqlException;
use models\Exception\Service\ServiceException;
use models\Exception\Transformer\TransformerException;
use models\Service\AlibabafavourService;
use models\Service\MemberoauthService;
use models\Service\MemberService;
use models\Service\SystemService;
use models\Service\TbkfavourService;
use models\Service\TbkproductService;
use Yaf\Exception;
use Yaf\Registry;
use youliPhpLib\Common\PwdAss;
use youliPhpLib\Common\StringOperation;

class Member
{
    /**
     * 通过会员编号获取指定的会员信息
     * @param $member_id
     * @return array|mixed|null
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getMemberInfoById($member_id) {
        try {
            $member = MemberService::getInstance()->getOne($member_id);
            $member['avatar'] = (strpos($member['avatar'], 'http://') === false && strpos($member['avatar'], 'http://') === false ? Registry::get('config')['application']['host'] : '') . $member['avatar'];
            $member['integral'] = (string)intval($member['integral']);
            return $member;
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 通过会员编号查询所有上级会员
     * @param $member_id
     * @return mixed
     * @throws ModelSqlException
     */
    static public function getAllParentByMemberId($member_id) {
        $sql = "SELECT T2.id,T2.nickname, T2.mobile, T2.balance, T2.integral, T1.lvl FROM (SELECT @r AS _id, @STOP :=@STOP + IF(@r = 2 , 1 ,@STOP) AS STOP, (SELECT @r := parent FROM `member` WHERE id = _id) AS parent , " .
            "@l := @l + 1 AS lvl FROM (SELECT @r := " . $member_id . " , @l := 0 , @STOP := 0) vars, `member` h WHERE @STOP < 1) T1 JOIN `member` T2 ON T1._id = T2.id ORDER BY T1.lvl DESC";

        $member_conn = MemberModel::getInstance()->getConn();
        $member_conn->query($sql);
        return $member_conn->fetchAll($sql);
    }

    /**
     * 通过会员编号 获取他的下级，下下级会员编号
     * @param $member_id
     * @return array
     * @throws ModelSqlException
     */
    static public function getAllFriendByMemberId($member_id) {
        $sql = "SELECT DATA.id, DATA.parent FROM " .
            "(SELECT @ids AS _ids, (SELECT @ids := GROUP_CONCAT(id) FROM `member` WHERE FIND_IN_SET(parent , @ids)) AS cids, @l := @l + 1 AS LEVEL ".
            "FROM `member`, (SELECT @ids := '" . $member_id . "' , @l := 0) AS b WHERE @ids IS NOT NULL) AS id, `member` AS DATA ".
            "WHERE FIND_IN_SET(DATA .id , _ids) ORDER BY LEVEL, id";

        $member_conn = MemberModel::getInstance()->getConn();
        $member_conn->query($sql);
        $member_arr = $member_conn->fetchAll($sql);

        return array_column($member_arr, 'parent', 'id');

    }

    /**
     * 获取指定会员的间属好友
     * @param $parameters
     * @return array
     * @throws MemberException
     * @throws ModelException
     * @throws ModelReflectionException
     */
    static public function getAllIndirectMember($parameters) {
        try {
            $return_count = false;
            $count_sql = "SELECT count(DATA.id) as total FROM " .
                "(SELECT @ids AS _ids, (SELECT @ids := GROUP_CONCAT(id) FROM `member` WHERE FIND_IN_SET(parent , @ids)) AS cids, @l := @l + 1 AS LEVEL ".
                "FROM `member`, (SELECT @ids := '" . $parameters['parent'] . "' , @l := 0) AS b WHERE @ids IS NOT NULL) AS id, `member` AS DATA ".
                "WHERE FIND_IN_SET(DATA .id , _ids) and DATA.id != '" . $parameters['parent'] . "' AND DATA.parent != '" . $parameters['parent'] . "'";

            if (isset($parameters['get_indirect_member_by_start_date'])) {
                $count_sql .= " AND DATA .created_at > '" . $parameters['get_indirect_member_by_start_date'] . "'";
                $return_count = true;
            }
            if (isset($parameters['get_indirect_member_by_end_date'])) {
                $count_sql .= " AND DATA .created_at < '" . $parameters['get_indirect_member_by_end_date'] . "'";
                $return_count = true;
            }
            $count_sql .= " ORDER BY LEVEL, id";

            $model = MemberModel::getInstance();
            $model->page = isset($parameters['page']) ? $parameters['page'] : 1;
            $model->page_size = isset($parameters['page_size']) ? $parameters['page_size'] : 10;
            $count = $model->query($count_sql);

            if ($return_count === true)
                return $count;

            if (is_array($count) && !empty($count) && isset($count[0]['total']) && $count[0]['total'] > 0) {
                $model->genMeta($count[0]['total']);

                $start_pos = ($model->meta->current_page - 1) * $model->meta->per_page;
                $end_pos = $model->meta->per_page;

                $sql = "SELECT DATA.id, DATA.mobile, DATA.nickname,DATA.avatar, DATA.created_at FROM " .
                    "(SELECT @ids AS _ids, (SELECT @ids := GROUP_CONCAT(id) FROM `member` WHERE FIND_IN_SET(parent , @ids)) AS cids, @l := @l + 1 AS LEVEL ".
                    "FROM `member`, (SELECT @ids := '" . $parameters['parent'] . "' , @l := 0) AS b WHERE @ids IS NOT NULL) AS id, `member` AS DATA ".
                    "WHERE FIND_IN_SET(DATA .id , _ids) and DATA.id != '" . $parameters['parent'] . "' AND DATA.parent != '" . $parameters['parent'] . "' ORDER BY LEVEL, id LIMIT " . $start_pos . ", " . $end_pos;

                $result = $model->query($sql);
                $model->setModelProperty($result, true);
            }

            if (empty($model->data))
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);

            foreach ($model->data as $idx => $member) {
                if (isset($parameters['from_api']) && $parameters['from_api'] === true)
                    $model->data[$idx]['mobile'] = strpos($member['mobile'], '****') === false ?
                        substr($member['mobile'], 0, 3) . '****' . substr($member['mobile'], 7) :
                        $member['mobile'];
            }

            return [
                'data' => $model->data,
                'meta' => $model->meta
            ];
        } catch (MemberException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
        }

    }

    /**
     * 通过商品data列表查询这些1688商品或tbk商品是否被当前登陆账号收藏
     * @param array $product_lists
     * @param int $type
     * @return array
     */
    static public function getFavoursByProductLists($product_lists = [], $type = 0) {
        $favour_product_id_arr = [];
        try {
            $product_id_arr = array_column($product_lists['data'], 'product_id');
            $product_id_arr = array_unique(array_filter($product_id_arr));

            if (Registry::get('jwt_info')->id) {
                if (count($product_id_arr) == 1) {
                    if ($type == 1) {
                        $favour_list = TbkfavourService::getInstance()->getList(1, count($product_id_arr), 'desc','created_at',
                            ['groupOp' => 'AND', 'rules' => [
                                ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                                ['field' => 'product_id', 'op' => 'eq', 'data' => implode(',', array_values($product_id_arr))]]]);
                    } else {
                        $favour_list = AlibabafavourService::getInstance()->getList(1, count($product_id_arr), 'desc','created_at',
                            ['groupOp' => 'AND', 'rules' => [
                                ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                                ['field' => 'product_id', 'op' => 'eq', 'data' => implode(',', array_values($product_id_arr))]]]);
                    }
                } else {
                    if ($type == 1) {
                        $favour_list = TbkfavourService::getInstance()->getList(1, count($product_id_arr), 'desc','created_at',
                            ['groupOp' => 'AND', 'rules' => [
                                ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                                ['field' => 'product_id', 'op' => 'in', 'data' => implode(',', $product_id_arr)]]]);
                    } else {
                        $favour_list = AlibabafavourService::getInstance()->getList(1, count($product_id_arr), 'desc','created_at',
                            ['groupOp' => 'AND', 'rules' => [
                                ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                                ['field' => 'product_id', 'op' => 'in', 'data' => implode(',', $product_id_arr)]]]);
                    }
                }

                $favour_product_id_arr = array_column($favour_list['data'], 'product_id');
            }
        } catch (\Exception $e) {

        } finally {
            foreach ($product_lists['data'] as $idx => $product_info) {
                $product_lists['data'][$idx]['is_favour'] = (int)in_array($product_info['product_id'], $favour_product_id_arr);
                $product_lists['data'][$idx]['is_coupon'] = 0;
            }

            return $product_lists;
        }
    }

    /**
     * 获取收藏列表
     * @param array $parameters
     * @return array
     * @throws AlibabacategoryException
     * @throws AlibabaproductException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getFavoursProduct($parameters = []) {
        $rules = $condition = [];
        if (isset($parameters['from_api']) && $parameters['from_api'] === true)
            array_push($rules, ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id]);

        if (!empty($rules))
            $condition = ['groupOp' => 'AND', 'rules' => $rules];

        if (! isset($parameters['type']))
            $favours = AlibabafavourService::getInstance()->getList(
            isset($parameters['page']) ? $parameters['page'] : 1,
            isset($parameters['page_size']) ? $parameters['page_size'] : 10,
            isset($parameters['sort']) ? $parameters['sort'] : 'desc',
            isset($parameters['order']) ? $parameters['order'] : 'created_at',
            $condition
        );
        else if ($parameters['type'] == 1) {
            $favours = TbkfavourService::getInstance()->getList(
                isset($parameters['page']) ? $parameters['page'] : 1,
                isset($parameters['page_size']) ? $parameters['page_size'] : 10,
                isset($parameters['sort']) ? $parameters['sort'] : 'desc',
                isset($parameters['order']) ? $parameters['order'] : 'created_at',
                $condition
            );
        }


        $product_id_arr = array_column($favours['data'], 'product_id');

        $product['data'] = [];
        if (count($product_id_arr) == 1) {
            if (isset($parameters['type']) && $parameters['type'] == 1)
                $product = TbkProduct::getTbkProductByProductId(implode('', $product_id_arr));
            else
                $product = AlibabaProduct::getProduct(['id' => implode('', $product_id_arr), 'from_api' => true]);
        } else if (count($product_id_arr) > 1) {
            if (isset($parameters['type']) && $parameters['type'] == 1)
                $product = TbkProduct::getTbkProductList(['page' => 1, 'page_size' => count($product_id_arr),
                    'sort' => 'desc', 'order' => 'product_id', 'product_id' => $product_id_arr, 'from_api' => true, 'from_favour' => true]);
            else
                $product = AlibabaProduct::getProductList(['page' => 1, 'page_size' => count($product_id_arr),
                    'sort' => 'desc', 'order' => 'product_id', 'product_id' => $product_id_arr, 'from_api' => true]);
        }

        return [
            'data' => $product['data'],
            'meta' => $favours['meta']
        ];
    }

    /**
     * 取消收藏1688商品
     * @param array $parameters
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function cancelFavourAlibabaProduct($parameters = []) {
        try {
            $favour = AlibabafavourService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'product_id', 'op' => 'eq', 'data' => $parameters['id']],
                ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id]
            ]]);
            if (empty($favour))
                throw new MemberException(MemberException::NOT_YET_FAVOUR, MemberException::NOT_YET_FAVOUR_NO);

            $sql = "DELETE FROM `alibabafavour` WHERE `product_id` = '" . $parameters['id'] . "' AND `member_id` = '" . Registry::get('jwt_info')->id . "'";
            AlibabafavourModel::getInstance()->getConn()->executeQuery($sql);
        } catch (MemberException $e) {
            throw $e;
        } catch (DriverException $e) {
            throw new MemberException(MemberException::CANCEL_FAVOUR_FAILURE, MemberException::CANCEL_FAVOUR_FAILURE_NO);
        }  catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }

    }

    /**
     * 收藏1688商品
     * @param array $parameters
     * @throws AlibabacategoryException
     * @throws AlibabaproductException
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function favourAlibabaProduct($parameters = []) {
        try {
            // 读取redis中的数据
            if (false !== $product_in_redis = Registry::get('redis_string')->getString('alibaba_product:' . $parameters['id']))
                $product['data'][] = json_decode($product_in_redis, true);
            // 读取数据库中的数据
            else
                $product = AlibabaProduct::getProduct(['id' => $parameters['id'], 'from_api' => true]);

            if (empty($product['data']))
                throw new AlibabaproductException(AlibabaproductException::ALIBABAPRODUCT_IS_NOT_EXISTS, AlibabaproductException::ALIBABAPRODUCT_IS_NOT_EXISTS_NO);

//            $sql = "INSERT INTO `alibabafavour` (`product_id`, `member_id`) VALUE ('" . $parameters['id'] . "', '" . Registry::get('jwt_info')->id . "')";
//            AlibabafavourModel::getInstance()->getConn()->executeQuery($sql);
        } catch (AlibabaproductException $e) {
            throw $e;
        }

        $conn = AlibabafavourModel::getInstance()->getConn();
        $conn->beginTransaction();
        try {
            // 添加用户数收藏数
            $sql = "INSERT INTO `alibabafavour` (`product_id`, `member_id`) VALUE ('" . $parameters['id'] . "', '" . Registry::get('jwt_info')->id . "')";
            $conn->executeQuery($sql);

            // 商品收藏数
            $update_product_favours = "UPDATE `alibabaproduct` SET `favours` = `favours` + 1 WHERE `product_id` = '" . $parameters['id'] . "'";
            $conn->executeQuery($update_product_favours);
            $conn->commit();

        } catch (\Exception $e) {
            $conn->rollback();
            throw new MemberException(MemberException::REPEAT_FAVOUR, MemberException::REPEAT_FAVOUR_NO);
        }
    }

    /**
     * 获取登陆用户的足迹
     * @param array $parameters
     * @return array|mixed
     * @throws MemberException
     */
    static public function getFootprint($parameters = []) {
        $product = [];
        try {
            if (! Registry::get('jwt_info')->jti) {
                throw new MemberException(MemberException::LOGIN_FIRST, MemberException::LOGIN_FIRST_NO);
            }

            $date = !empty($parameters['date']) ? $parameters['date'] : date("Y-m-d", time());
            if (isset($parameters['type']) && $parameters['type'] == 1)
                $key = 'tbk_footprint:' . Registry::get('jwt_info')->jti;
            else
                $key = 'alibaba_footprint:' . Registry::get('jwt_info')->jti;

            $return_arr = [];

            $total = Registry::get('redis_list')->getLen($key);
            $page = isset($parameters['page']) ? $parameters['page'] : 1;
            $page_size = isset($parameters['page_size']) ? $parameters['page_size'] : 10;
            $total_page = ceil($total / $page_size);
            $start = $page <= $total_page ? ($page - 1) * 10 : ($total_page - 1) * $page_size;
            $end = ($page_size * $page) - 1;
            $data = Registry::get('redis_list')->getList($key, $start, (int)$end);
            $return_arr['meta'] = [
                'total' => Registry::get('redis_list')->getLen($key),
                'total_pages' => $total_page,
                'per_page' => $page_size,
                'current_page' => $page,
                'count' => $page_size
            ];
            if ($page < $total_page)
                $return_arr['meta']['link']['next_page'] = $page + 1;
            if ($page > 1 && $total_page >= $page)
                $return_arr['meta']['link']['prev_page'] = $page - 1;

            $product_id_arr = [];
            foreach ($data as $idx => $val) {
                array_push($product_id_arr, $val['value']);
            }

            $product_id_arr = array_unique($product_id_arr);
            if (count($product_id_arr) == 1) {
                if (! isset($parameters['type']))
                    $product = AlibabaProduct::getProduct(['id' => implode('', $product_id_arr), 'from_api' => true]);
                else if ($parameters['type'] == 1)
                    $product = TbkProduct::getTbkProductByProductId(implode('', $product_id_arr));
            }
            else if (count($product_id_arr) > 1) {
                if (! isset($parameters['type']))
                    $product = AlibabaProduct::getProductList(['page' => 1, 'page_size' => count($product_id_arr), 'desc', 'product_id',
                        'product_id' => $product_id_arr, 'from_api' => true]);
                else if ($parameters['type'] == 1)
                    $product = TbkProduct::getTbkProductList(['page' => 1, 'page_size' => count($product_id_arr), 'desc', 'product_id',
                        'product_id' => $product_id_arr]);
            }

            $product_id_array = array_column($product['data'], 'product_id');

            $return_arr['data'] = [];
            foreach ($data as $idx => $val) {
                if (false !== $key = array_search($val['value'], $product_id_array)) {
                    $product['data'][$key]['view_time'] = date("Y-m-d H:i:s", $val['score'] / 1000);
                    array_push($return_arr['data'], $product['data'][$key]);
                }
            }

            return $return_arr;
        } catch (MemberException $e) {
            throw $e;
        } catch (\Exception $e) {
            return $product;
        }
    }

    /**
     * 保存用户足迹
     * @param $product
     * @param string $type
     * @return bool
     */
    static public function footprint($product, $type = 'alibaba') {
        try {
            if (! isset($product['product_id']) || empty($product['product_id']))
                throw new AlibabaproductException(AlibabaproductException::ALIBABAPRODUCT_ID_IS_EMPTY, AlibabaproductException::ALIBABAPRODUCT_ID_IS_EMPTY_NO);

            $timestamp = sprintf('%.0f', microtime(true) * 1000);
            $expire = strtotime(date("Y-m-d", strtotime('+1 month'))) - sprintf('%.0f', ($timestamp / 1000));
            $product_cache_name = $type . '_product:' . $product['product_id'];
            // 保存商品信息
            Registry::get('redis_string')->genString($product_cache_name, json_encode($product));

            if (Registry::get('jwt_info')->jti) {
//                $footprint_cache_name = $type . '_footprint:' . date("Y-m-d", sprintf('%.0f', ($timestamp / 1000))) . ':' . (string)Registry::get('jwt_info')->jti;
                $footprint_cache_name = $type . '_footprint:' . (string)Registry::get('jwt_info')->jti;
                Registry::get('redis_list')->genList($footprint_cache_name,
                    [['score' => $timestamp, 'value' => $product['product_id']]], $expire);
            }
        } catch (AlibabaproductException $e) {

        } finally {
            return true;
        }
    }

    /**
     * 通过手机号码查询会员编号
     * @param string $mobile
     * @return mixed
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getMemberIdByMobile($mobile = '') {
        try {
            $member = MemberService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'mobile', 'op' => 'nc', 'data' => $mobile . '%']
            ]]);
            if (! $member)
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
            return $member['id'];
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        } catch (Exception $e) {
            exit(json_encode($e->getMessage()));
        }
    }

    /**
     * @param array $module_list
     * @param bool $hide_mobile
     * @return array
     */
    static public function getMembersByModules($module_list = [], $hide_mobile = true) {
        $member_nickname_id_arr = $member_mobile_id_arr = $member_avatar_id_arr = [];
        try {
            $member_id_arr = array_unique(array_column($module_list['data'], 'member_id'));

            $member = [];
            if (count($member_id_arr) == 1)
                $member['data'][] = MemberService::getInstance()->getOne(implode('', $member_id_arr));
            else if (count($member_id_arr) > 1)
                $member = MemberService::getInstance()->getList(1, count($member_id_arr), 'desc', 'id',
                    ['groupOp' => 'AND', 'rules' => [
                        ['field' => 'id', 'op' => 'in', 'data' => implode(',', $member_id_arr)]]]);

            if (!empty($member)) {
                $member_nickname_id_arr = array_column($member['data'], 'nickname', 'id');
                $member_mobile_id_arr = array_column($member['data'], 'mobile', 'id');
                $member_avatar_id_arr = array_column($member['data'], 'avatar', 'id');
            }

        } catch (\Exception $e) {

        } finally {
            foreach ($module_list['data'] as $idx => $module_info) {
                $module_list['data'][$idx]['member_nickname'] = isset($member_nickname_id_arr[$module_info['member_id']]) ?
                    $member_nickname_id_arr[$module_info['member_id']] : '';
//                $module_list['data'][$idx]['member_mobile'] = isset($member_mobile_id_arr[$module_info['member_id']]) ?
//                    $member_mobile_id_arr[$module_info['member_id']] : '';
                $module_list['data'][$idx]['member_mobile'] = isset($member_mobile_id_arr[$module_info['member_id']]) ?
                    (strpos($member_mobile_id_arr[$module_info['member_id']], '****') === false && $hide_mobile ?
                        substr($member_mobile_id_arr[$module_info['member_id']], 0, 3) . '****' . substr($member_mobile_id_arr[$module_info['member_id']], 6
                        ) :
                        $member_mobile_id_arr[$module_info['member_id']]) : '';
                $module_list['data'][$idx]['member_avatar'] = isset($member_avatar_id_arr[$module_info['member_id']]) ?
                    Registry::get('config')['application']['host'] . $member_avatar_id_arr[$module_info['member_id']] : '';
            }

            return $module_list;
        }
    }

    /**
     * 编辑会员
     * @param array $parameters
     * @return array|mixed|null
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function editMember($parameters = []) {
        try {
            if (! isset($parameters['id']) || empty($parameters['id']))
                throw new MemberException(MemberException::MEMBER_ID_IS_EMPTY, MemberException::MEMBER_ID_IS_EMPTY_NO);

            // 客户端、前端的调用
            if (isset($parameters['from_api']) && $parameters['from_api'] === true &&
                Registry::get('jwt_info')->id != $parameters['id']) {
                throw new MemberException(MemberException::EDIT_DENIED, MemberException::EDIT_DENIED_NO);
            }

            $update_arr = [];
            $origin = false;
            if (isset($parameters['nickname']))
                $update_arr['nickname'] = $parameters['nickname'];

            if (isset($parameters['avatar'])) {
//                $origin = isset($parameters['http_origin']) && ! empty($parameters['http_origin']) ?
//                    $parameters['http_origin'] : $_SERVER['HTTP_ORIGIN'];
//                $update_arr['avatar'] = str_replace($origin, '', $parameters['avatar']);
                $update_arr['avatar'] = str_replace(Registry::get('config')['application']['host'], '', $parameters['avatar']);
            }

            if (isset($parameters['password'])) {
                $password = PwdAss::getInstance(8, true)->HashPassword($parameters['password']);
                $update_arr['password'] = $password;
            }
            if (isset($parameters['paypassword'])) {
                $password = PwdAss::getInstance(8, true)->HashPassword($parameters['paypassword']);
                $update_arr['pay_password'] = $password;
            }

            if (isset($parameters['stats']))
                $update_arr['stats'] = $parameters['stats'];

            if (!empty($update_arr)) {
                $member = MemberService::getInstance()->update($update_arr, $parameters['id']);
                $member['avatar'] = (strpos($member['avatar'], 'http://') === false && strpos($member['avatar'], 'http://') === false ? Registry::get('config')['application']['host'] : '') . $member['avatar'];
            } else
                $member = MemberService::getInstance()->getOne($parameters['id']);

            return $member;
        } catch (MemberException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new MemberException(MemberException::MEMBER_EDIT_FAILURE, MemberException::MEMBER_EDIT_FAILURE_NO);
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 用户登陆
     * @param array $parameters
     * @return array|mixed|null
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function login($parameters = []) {
        try {
            if (!isset($parameters['mobile']) || empty($parameters['mobile']))
                throw new MemberException(MemberException::MEMBER_MOBILE_EMPTY, MemberException::MEMBER_MOBILE_EMPTY_NO);

            if (!isset($parameters['password']) || empty($parameters['password']))
                throw new MemberException(MemberException::MEMBER_PASSWORD_EMPTY, MemberException::MEMBER_PASSWORD_EMPTY_NO);

            // 查询用户
            $member = MemberService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'mobile', 'op' => 'eq', 'data' => $parameters['mobile']]
            ]]);
            if (empty($member))
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);

            // 判断用户状态是否合法
            if ($member['stats'] != 1)
                throw new MemberException(MemberException::INVALID_STATS, MemberException::INVALID_STATS_NO);

            // 判断密码是否正确
            if (PwdAss::getInstance(8, true)->CheckPassword($parameters['password'], $member['password']) === false)
                throw new MemberException(MemberException::WRONG_PASSWORD, MemberException::WRONG_PASSWORD_NO);

            // 判断是否需要修改registration_id, device_type, device_no
            $update_arr = [];
            if (isset($parameters['device_no']) && $parameters['device_no'] != $member['device_no'])
                $update_arr['device_no'] = $parameters['device_no'];
            if (isset($parameters['registration_id']) && $parameters['registration_id'] != $member['registration_id'])
                $update_arr['registration_id'] = $parameters['registration_id'];
            if (isset($parameters['device_type']) && $parameters['device_type'] != $member['device_type'])
                $update_arr['device_type'] = $parameters['device_type'];

            // 修改登陆次数，上次登陆时间，上次登陆ip
            $update_arr['login_times'] = $member['login_times'] + 1;
            $update_arr['last_login_time'] = date('Y-m-d H:i:s', time());
            $update_arr['last_login_ip'] = StringOperation::getIP();

            $member = MemberService::getInstance()->update($update_arr, $member['id']);

            $member['avatar'] = (strpos($member['avatar'], 'http://') === false && strpos($member['avatar'], 'http://') === false ? Registry::get('config')['application']['host'] : '') . $member['avatar'];
            $member['integral'] = (string)intval($member['integral']);
            // 生成jwt
            $member['jwt'] = AccessToken4Api::generateJWT($member['mobile'], $member['id'], $member['parent'], $member['uuid']);

            // 获取当前用户是否绑定过淘宝第三方授权登录
            $member_oauth = MemberModel::getInstance()->query(
                "SELECT o.`id` FROM `oauth` AS o LEFT JOIN `memberoauth` AS mo ON o.`id` = mo.`oauth_id` WHERE o.`type` = 4 AND mo.`member_id` = " . $member['id']
            );
            $member['is_tb_oauth'] = (int)!empty($member_oauth);

            return $member;
        } catch (MemberException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }


    }

    /**
     * 会员列表
     * @param array $parameters
     * @return array|mixed
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getMemberList($parameters = []) {
        try {
            $rules = $condition = [];
            if (isset($parameters['parent']))
                array_push($rules, ['field' => 'parent', 'op' => 'eq', 'data' => $parameters['parent']]);

            if (isset($parameters['stats']))
                array_push($rules, ['field' => 'stats', 'op' => 'eq', 'data' => $parameters['stats']]);

            if (isset($parameters['mobile']))
                array_push($rules, ['field' => 'mobile', 'op' => 'nc', 'data' => $parameters['mobile'] . '%']);

            if (isset($parameters['nickname']))
                array_push($rules, ['field' => 'nickname', 'op' => 'nc', 'data' => $parameters['nickname'] . '%']);

            if (!empty($rules))
                $condition = ['groupOp' => 'AND', 'rules' => $rules];
            $members = MemberService::getInstance()->getList(
                isset($parameters['page']) ? $parameters['page'] : 1,
                isset($parameters['page_size']) ? $parameters['page_size'] : 10,
                isset($parameters['sort']) ? $parameters['sort'] : 'desc',
                isset($parameters['order']) ? $parameters['order'] : 'id',
                $condition
            );

            $members = static::getParentsByModules($members);

            foreach ($members['data'] as $idx => $member_info) {
                $members['data'][$idx]['avatar'] = !empty($member_info['avatar']) ?
                    'http://' . $_SERVER['HTTP_HOST'] . $member_info['avatar'] : '';
                if (isset($parameters['from_api']) && $parameters['from_api'] === true)
                    $members['data'][$idx]['mobile'] = strpos($member_info['mobile'], '****') === false ?
                        substr($member_info['mobile'], 0, 3) . '****' . substr($member_info['mobile'], 7) :
                        $member_info['mobile'];
            }

            return $members;
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
        } catch (ModelReflectionException $e) {
            throw $e;

        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 获取用户的上级
     * @param array $modules_list
     * @return array
     */
    static public function getParentsByModules($modules_list = []) {
        try {
            $members = $parent_name_id_arr = [];

            $parent_id = array_column($modules_list['data'], 'parent');
            $parent_id = array_unique($parent_id);

            if (count($parent_id) == 1)
                $members['data'][] = MemberService::getInstance()->getOne(implode('', $parent_id));
            else if (count($parent_id) > 1) {
                $members = MemberService::getInstance()->getList(1, count($parent_id), 'desc', 'id',
                    ['groupOp' => 'AND', 'rules' => [
                        ['field' => 'id', 'op' => 'in', 'data' => implode(',', $parent_id)]]]);
            }

            $parent_name_id_arr = array_column($members['data'], 'nickname', 'id');

        } catch (\Exception $e) {

        } finally {
            foreach ($modules_list['data'] as $idx => $member_info) {
                $modules_list['data'][$idx]['parent_nickname'] = isset($parent_name_id_arr[$member_info['parent']]) ?
                    $parent_name_id_arr[$member_info['parent']] : '';
            }
            return $modules_list;
        }

    }

    static public function genInviteCode($uuid = '') {
        $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        $key = "youlimall";
        $string_hash = md5($key . $uuid);
        $len = strlen($string_hash);

        $invite_code_list = [];
        #将加密后的串分成4段，每段4字节，对每段进行计算，一共可以生成四组短连接
        for ($i = 0; $i < 4; $i++) {
            $invite_code = '';
            $string_hash_piece = substr($string_hash,  $i * $len / 4, $len / 4);
            #将分段的位与0x3fffffff做位与，0x3fffffff表示二进制数的30个1，即30位以后的加密串都归零
            $hex = hexdec($string_hash_piece) & 0x3fffffff; #此处需要用到hexdec()将16进制字符串转为10进制数值型，否则运算会不正常

            #生成6位短连接
            for ($j = 0; $j < 6; $j++) {
                #将得到的值与0x0000003d,3d为61，即charset的坐标最大值
                $invite_code .= $charset[$hex & 0x0000003d];
                #循环完以后将hex右移5位
                $hex = $hex >> 5;
            }

            $invite_code_list[] = $invite_code;
        }

        return $invite_code_list;
    }

    /**
     * 用户注册
     * @param array $parameters
     * @return array|bool
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws TransformerException
     */
    static public function register($parameters = []) {
        // 生成uuid
        $hash_id = new Hashids('ylmall', 16, 'abcdefghijklmnopqrstuvwxyz01234569');
        $uuid = $hash_id->encode($parameters['mobile'] . time());

        $invite_code_list = \models\Business\Member::genInviteCode($uuid);

        $password = PwdAss::getInstance(8, true)->HashPassword($parameters['password']);

        $mobile_exists = MemberService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
            ['field' => 'mobile', 'op' => 'eq', 'data' => $parameters['mobile']]
        ]]);
        if (!empty($mobile_exists))
            throw new MemberException(MemberException::MEMBER_MOBILE_EXISTS, MemberException::MEMBER_MOBILE_EXISTS_NO);

        $parent_id = 0;
        if (isset($parameters['invite_code'])) {
            try {
                $parent = MemberService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                    ['field' => 'uuid', 'op' => 'eq', 'data' => $parameters['invite_code']]]]);
                $parent_id = $parent['id'];

                $conn = MemberModel::getInstance()->getConn();
                $conn->beginTransaction();
                $sql = "UPDATE `member` SET `direct` = `direct` + 1 WHERE `id` = " . $parent_id;
                $conn->executeQuery($sql);
                if (!empty($parent['parent'])) {
                    $sql = "UPDATE `member` SET `indirect` = `indirect` + 1 WHERE `id` = " . $parent['parent'];
                    $conn->executeQuery($sql);
                }
                $conn->commit();
                $parameters['parent'] = $parent_id;
            } catch (\Exception $e) {

            }
        }

        $member = false;
        while($member === false && count($invite_code_list) > 0) {
            $invite_code = array_shift($invite_code_list);
            try {
                $member = MemberService::getInstance()->create(
                    $invite_code, $parameters['mobile'], '豆子优品' . mt_rand(10000, 99999), $password, '','/upload/avatar/default.png', $parent_id,
                    isset($parameters['device_no']) ? $parameters['device_no'] : '',
                    isset($parameters['registration_id']) ? $parameters['registration_id'] : '',
                    $parameters['device_type'], 1, 0.00, 0.00,0.00, 0, 0.00,
                    0, 0, 0, 0, 0, 0, 0,
                    0, 0, date('Y-m-d H:i:s', time()),
                    StringOperation::getIP(), date('Y-m-d H:i:s', time())
                );
            } catch (Exception $e) {
                Registry::get('db_log')->err('用户注册失败: ' . $e->getMessage());
            }
        }

        if ($member === false)
            throw new MemberException(MemberException::MEMBER_CREATE_FAILURE, MemberException::MEMBER_CREATE_FAILURE_NO);

        return $member;
        /*try {
            // $uuid = "", $mobile = "", $nickname = "", $password = "", $avatar = "", $parent = 0,
            // $device_no = "", $registration_id = "",
            // $device_type = 0, $stats = 0, $coupon_amount = 0.00, $tb_amount = 0.00, $balance = 0.00,
            // $withdraw = 0.00, $coupon_platform_income = 0.00, $direct = 0, $indirect = 0, $coupon_order_number = 0, $return_order_number = 0,
            // $refund_order_number = 0, $login_times = 0, $last_login_time = "", $last_login_ip = "", $created_at = ""
            return MemberService::getInstance()->create(
                $uuid, $parameters['mobile'], '', $password, '', $parent_id,
                isset($parameters['device_no']) ? $parameters['device_no'] : '', $parameters['registration_id'],
                $parameters['device_type'], 1, 0.00, 0.00, 0, 0.00,
                0, 0, 0, 0, 0, 0,
                0, 0, date('Y-m-d H:i:s', time()),
                StringOperation::getIP(), date('Y-m-d H:i:s')
            );
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new MemberException(MemberException::MEMBER_CREATE_FAILURE, MemberException::MEMBER_CREATE_FAILURE_NO);
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }*/
    }

    /**
     * 获取指定会员、指定日期的新增好友(直属+间属)
     * @param int $member_id
     * @param string $start_date
     * @param string $end_date
     * @return mixed
     * @throws MemberException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     */
    static public function getFriendIncrementByDate($member_id = 0, $start_date = '', $end_date = '') {
        // 测试用
//        $start_date = '2020-05-06';
//        $end_date = '2020-05-07';
        $where_arr = $direct_where_arr = [];
        if (empty($start_date))
            $start_date = date('Y-m-d', time());
        array_push($where_arr, '`created_at` > "' . $start_date . '"');

        if (empty($end_date))
            $end_date = date('Y-m-d', time() + 86400);
        array_push($where_arr, '`created_at` < "' . $end_date . '"');

        if (! empty($member_id))
            array_push($where_arr, '`parent` = "' . $member_id . '"');

        // 获取指定日期 指定会员的直属好友
        $sql = "select count(`id`) as total, FROM_UNIXTIME(UNIX_TIMESTAMP(`created_at`), '%Y-%m-%d') as register from `member` ";
        if (!empty($where_arr))
            $sql .= ' WHERE ' . implode(' AND ', $where_arr);
        $sql .= "group by `register`";
        $model = MemberModel::getInstance()->getConn();
        $result = $model->query($sql);
        $increment_by_date = $result->fetch();
        $direct_increment = $increment_by_date === false ? 0 : $increment_by_date['total'];

        // 获取指定日期 指定会员的间属好友
        $indirect_increment_by_date = self::getAllIndirectMember(['parent' => $member_id, 'get_indirect_member_by_start_date' => $start_date, 'get_indirect_member_by_end_date' => $end_date]);
        $indirect_increment = empty($indirect_increment_by_date) ? 0 : $indirect_increment_by_date[0]['total'];

        return $indirect_increment + $direct_increment;
    }

    /**
     * 收藏淘宝客商品
     * @param array $parameters
     * @throws AlibabacategoryException
     * @throws AlibabaproductException
     * @throws MemberException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TbkproductException
     * @throws TransformerException
     */
    static public function favourTbkProduct($parameters = []) {
        try {
            // 读取redis中的数据
            if (false !== $product_in_redis = Registry::get('redis_string')->getString('tbk_product:' . $parameters['id']))
                $product['data'][] = json_decode($product_in_redis, true);
            // 读取数据库中的数据
            else
                $product['data'][] = TbkfavourService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                    ['field' => 'product_id', 'op' => 'eq', 'data' => $parameters['id']],
                    ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id]
                ]]);

            if (empty($product['data']))
                throw new TbkproductException(TbkproductException::TBKPRODUCT_IS_NOT_EXISTS, TbkproductException::TBKPRODUCT_IS_NOT_EXISTS_NO);

            $sql = "INSERT INTO `tbkfavour` (`product_id`, `member_id`) VALUE ('" . $parameters['id'] . "', '" . Registry::get('jwt_info')->id . "')";
            TbkfavourModel::getInstance()->getConn()->executeQuery($sql);
        } catch (AlibabacategoryException $e) {
            throw $e;
        } catch (AlibabaproductException $e) {
            throw $e;
        } catch (DriverException $e) {
            throw new MemberException(MemberException::REPEAT_FAVOUR, MemberException::REPEAT_FAVOUR_NO);
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 取消收藏淘宝客商品
     * @param array $parameters
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function cancelFavourTbkProduct($parameters = []) {
        try {
            $favour = TbkfavourService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'product_id', 'op' => 'eq', 'data' => $parameters['id']],
                ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id]
            ]]);
            if (empty($favour))
                throw new MemberException(MemberException::NOT_YET_FAVOUR, MemberException::NOT_YET_FAVOUR_NO);

            $sql = "DELETE FROM `tbkfavour` WHERE `product_id` = '" . $parameters['id'] . "' AND `member_id` = '" . Registry::get('jwt_info')->id . "'";
            AlibabafavourModel::getInstance()->getConn()->executeQuery($sql);
        } catch (MemberException $e) {
            throw $e;
        } catch (DriverException $e) {
            throw new MemberException(MemberException::CANCEL_FAVOUR_FAILURE, MemberException::CANCEL_FAVOUR_FAILURE_NO);
        }  catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 根据拼团失败会员编号、订单金额、返金豆比例，给拼团失败会员及其上级、上上级会员返回金豆
     * @param $fail_member_id
     * @param $order_amount 销售价
     * @param float $cost 成本价
     * @param float $num 第几笔返利
     * @param float $title 商品标题
     * @param float $sn 订单号
     * @param bool $return_balance
     * @return array
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws OrderException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function calCouponFailureMemberIntegral($fail_member_id, $order_amount, $cost,$fee=0, $return_balance = true,$num=1,$title='',$sn='') {
        if (empty($fail_member_id))
            return [];
        if (empty($order_amount))
            throw new OrderException(OrderException::INVALID_ORDER_AMOUNT, OrderException::INVALID_ORDER_AMOUNT_NO);

        $fail_member_info = MemberService::getInstance()->getOne($fail_member_id);
        if (empty($fail_member_info))
            throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);

        $insert_turnover_arr = $update_balance_arr = [];
        // 读取系统信息
        $system = SystemService::getInstance()->getOne(1);
        $service_rate = $system['service_rate']? $system['service_rate']/100 : 0.00;
        $rebate_rate = $system['rebate_rate']?$system['rebate_rate']/100 : 0.00;
        //返利公式 商品差价=a商品售价（不包含运费且a）-b进货价（不包含运费）; 退款收取服务费=a*d服务费比例; 拼团失败返利比例=c
        //（a-b）*c-a*d*c>0 基础参数 a*d 否则 a*d*c  $faliparam=返利金额
        $profit=$order_amount-$cost;
        $service_cost=$order_amount*$service_rate;
        //拼团失败退回的金额
        $balance=$order_amount+$fee;
        if($profit-$service_cost>0){
            $faliparam=$service_cost;
        }else{
            $faliparam=$service_cost*$rebate_rate;
        }
        // 读取上级会员信息
        // 系统表中 晒单用户的上级用户的返利比例无不为0时，计算其返利金额
        $info = Member::getAllParentByMemberId($fail_member_id);
        // 读取商品的的积分比例、上级会员积分比例、上上级会员积分比例

        // 按照lvl排序，并只读取三级
        array_multisort(array_column($info, 'lvl'), SORT_ASC, $info);
        foreach ($info as $idx => $member_info) {
            $now = date('Y-m-d H:i:s', time());
            if ($idx <= 2) {
                if ($idx == 0)
                    $rate = $system['rebate_rate'];
                else if ($idx == 1)
                    $rate = $system['parent_rate'];
                else if ($idx == 2)
                    $rate = $system['sub_rate'];
                else
                    $rate = 0;

                // 晒单会员 晒单会员上级会员 晒单会员上上级会员 的返利比例不为0时 为指定会员增加积分并新增流水记录
                if ($rate != 0) {
                    //返利金额*返利比例*100（金豆比例）
                    if($num==1)
                     $integral = sprintf('%.0f', round($faliparam * $rate / 100 * 100 , 0));
                    else{
                        if($profit-$service_cost>0){
                            $integral = sprintf('%.0f', round(($profit-$service_cost) * $rate / 100 * 100 , 0));
                        }else{
                            $integral = sprintf('%.0f', round($faliparam * (1-$rate / 100) * 100 , 0));
                        }
                    }

                    // 拼团失败的会员，退回余额
                    if ($fail_member_info['id'] == $member_info['id']) {
                        array_push($update_balance_arr, [
                            'member_id' => $member_info['id'],
                            'integral' => '`integral` + ' . $integral,
                            'balance' => $return_balance === true ? '`balance`+' . $balance : '`balance`',
                            'coupon_order_number' => '`coupon_order_number` + 1'
                        ]);
                        if ($return_balance === true) {
                            array_push($insert_turnover_arr, ['member_id' => $member_info['id'], 'type' => 4,
                                'currency' => $member_info['balance'], 'amount' => $balance,
                                'remain' => round(($member_info['balance'] + $balance), 2), 'stats' => 1,
                                'remark' => '您在“'.$title.'”拼单中未拼中，归还余额。订单号：'.$sn,
                                'created_at' => $now]);
                        }
                    } else {
                        array_push($update_balance_arr, ['member_id' => $member_info['id'],
                            'balance' => '`balance`',
                            'integral' => '`integral` + ' . $integral,
                            'coupon_order_number' => '`coupon_order_number`']);
                    }
                    if($num==1){
                        $remark='未拼中商品第一笔金豆|您在“'.$title.'”拼单中未拼中，赠送第一笔金豆，第二笔待买家确认收货后赠送。订单号：'.$sn;
                        $remark1='好友未拼中商品第一笔金豆|您的好友“'.$info[0]['nickname'].'”在拼单中未拼中，赠送第一笔金豆，第二笔待买家确认收货后赠送';
                        $remark2='间属好友未拼中商品第一笔金豆|您的间属好友“'.$info[0]['nickname'].'”在拼单中未拼中，赠送第一笔金豆，第二笔待买家确认收货后赠送';
                    }else{
                        $remark='用户确认收货第二笔金豆|您在“'.$title.'”拼单中未拼中，买家已确认收货，赠送第二笔金豆。订单号：'.$sn;
                        $remark1='好友未拼中商品第二笔金豆|您的好友“'.$info[0]['nickname'].'”在拼单中未拼中，买家已确认收货，赠送第二笔金豆';
                        $remark2='间属好友未拼中商品第二笔金豆|您的间属好友“'.$info[0]['nickname'].'”在拼单中未拼中，买家已确认收货，赠送第二笔金豆';
                    }

                    array_push($insert_turnover_arr, ['member_id' => $member_info['id'], 'type' => 0,
                        'currency' => $member_info['integral'], 'amount' => $integral,
                        'remain' => round(($member_info['integral'] + $integral), 0), 'stats' => 1,
                        'remark' => $idx == 0 ?$remark : ($idx == 1 ? $remark1 : ($idx == 2 ? $remark2 : '赠送金豆')),
                        'created_at' => $now]);
                }
            }
        }

        $update_balance_sql = $insert_turnover_sql = '';
        // 修改余额
        if (!empty($update_balance_arr)) {
            foreach ($update_balance_arr as $row) {
                $update_balance_sql .= "UPDATE `member` SET `balance` = " . $row['balance'] . ", `integral` = " . $row['integral'] . ", `coupon_order_number` = " . $row['coupon_order_number'] . " WHERE `id` = '" . $row['member_id'] . "';";
                Registry::get('db_log')->info("拼单失败用户增加余额+积分、拼单失败上级/上上级用户增加积分sql: " . $update_balance_sql);
//                $conn->executeQuery($sql);
            }
        }

        // 修改turnover记录
        if (!empty($insert_turnover_arr)) {
            $sql = "INSERT INTO `turnover` (`" . implode("`, `", array_keys($insert_turnover_arr[0])) . "`) VALUES ";
            foreach ($insert_turnover_arr as $row) {
                $sql .= "('" . implode("', '", array_values($row)). "'),";
            }
            $insert_turnover_sql = substr($sql, 0, strrpos($sql, ',')) . ';';
            Registry::get('db_log')->info("拼单失败用户及其上级、上上级增加积分流水sql: " . $insert_turnover_sql);
//            $conn->executeQuery($sql);
        }

        return [$update_balance_sql, $insert_turnover_sql];
    }
}
